home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-02
/
exemod.zip
/
EXEMOD.C
< prev
next >
Wrap
Text File
|
1990-03-27
|
5KB
|
166 lines
/*
EXEMOD.C - Modify global variables in EXE or COM file
Kevin Dean
16 Kellythorne Drive
Don Mills, Ontario
Canada M3A 2L4
March 27, 1990
Modifies global variables in initialized data segment of EXE or COM files.
Cannot modify global variables that are declared but not initialized as these
lie in the BSS segment of the program and are not in fact in the EXE image file
itself.
Copyright (c) 1990 by Kevin Dean
For Turbo C versions 2.0 and above. This code is public domain.
*/
#include <dir.h>
#include <dos.h>
#include <errno.h>
#include <fcntl.h>
#include <io.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <exemod.h>
/***/
/*
Name exemodify
Function Modifies static data in EXE or COM files.
Syntax int exemodify(char *progname, int keepdt, [void *data1,
unsigned n1, [void *data2, unsigned n2, [ ... ]]]
NULL);
Prototype in exemod.h
Remarks exemodify modifies global variables in the initialized data
segment of the current EXE or COM file. In DOS versions 3.0
and up, exemodify takes the program name from _argv[0]. In DOS
versions below 3.0, exemodify searches the DOS path for the
program passed in progname.
If keepdt is true, then the original file date/time stamp is
preserved.
exemodify cannot modify global variables that are declared but
not initialized as these lie in the BSS segment of the program
and are not in fact in the EXE or COM image file itself.
WARNING: Huge model programs treat uninitialized data the same
as initialized data with values of 0 in that the uninitialized
data is also written to the EXE file. Because of the model,
the Turbo C startup code does not initialize this data to 0.
Since the compiler itself does not differentiate between
initialized and uninitialized data in the huge model, neither
can this module, and so any changes written to what was
intended to be the uninitialized data segment in the huge model
could have unpredictable results.
Return value exemodify returns the number of data items successfully
modified (which may not be the same as the number of items
passed) or -1 in case of error (such as file not found or
invalid EXE file format).
In the event of an error, the global variable errno is set to
one of the following:
ENOENT No such file or directory
EMFILE Too many open files
EACCES Permission denied
EINVACC Invalid access code
EINVFMT Invalid format
Portability exemodify is unique to DOS.
*/
int exemodify(const char *progname, int keepdt, ...)
{
char *pathptr; /* Pointer to program path */
char _progname[MAXPATH]; /* Program name */
int retcode; /* Function return code */
char ext[MAXEXT]; /* Program extension */
int progfile; /* Program file handle */
int iscomfile; /* True if program is a COM file */
struct exeheader exe; /* EXE file header */
long filelen; /* Program file length */
struct ftime dtstamp; /* Program date/time stamp */
va_list datalist; /* List of data items to be written to file */
char *data; /* Pointer to current data item */
unsigned n; /* Size of current data item */
long seeklen; /* Seek length into program file */
if (_osmajor < 3)
/* Search DOS PATH for program */
if ((pathptr = searchpath(progname)) != NULL)
strcpy(_progname, pathptr);
else
_progname[0] = 0;
else
/* Program name is 0th parameter in DOS versions 3.0 and up */
strcpy(_progname, _argv[0]);
/* Assume error */
retcode = -1;
if (_progname[0])
{
if ((progfile = open(_progname, O_RDWR | O_BINARY)) != -1)
{
iscomfile = fnsplit(_progname, NULL, NULL, NULL, ext) & EXTENSION && !strnicmp(ext, ".COM", 4);
if (!iscomfile && (read(progfile, &exe, EXEH_SIZE) != EXEH_SIZE || exe.id != EXE_ID))
/* File is not a COM file and does not have a valid EXE file header */
errno = EINVFMT;
else
{
/* Cannot write beyond end of file */
filelen = filelength(progfile);
if (keepdt)
/* Save date/time stamp */
getftime(progfile, &dtstamp);
retcode = 0;
va_start(datalist, keep_attribs);
while ((data = va_arg(datalist, char *)) != NULL)
{
if (iscomfile)
/* Seek length is data offset - PSP size */
seeklen = FP_OFF(data) - 256;
else
/* Seek length is (data segment - (PSP + PSP size) + EXE size) * 16 + data offset */
seeklen = ((unsigned long)(FP_SEG(data) - (_psp + 16) + exe.size) << 4) + (unsigned long)FP_OFF(data);
n = va_arg(datalist, unsigned);
if (seeklen + n <= filelen && lseek(progfile, seeklen, SEEK_SET) != -1L && write(progfile, data, n) == n)
/* Seek and write was successful */
retcode++;
}
va_end(datalist);
if (keepdt)
/* Restore date/time stamp */
setftime(progfile, &dtstamp);
}
close(progfile);
}
}
else
/* File not found */
errno = ENOENT;
return (retcode);
}